package com.zkingsoft.common.interceptor;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.util.UrlPathHelper;

import com.matrix.core.constance.MatrixConstance;
import com.matrix.core.constance.SystemErrorCode;
import com.matrix.core.exception.GlobleException;
import com.matrix.core.tools.LogUtil;
import com.matrix.core.tools.WebUtil;
import com.zkingsoft.common.authority.DefaultAuthorityManager;
import com.zkingsoft.common.bean.SysUsers;
import com.zkingsoft.common.constance.AppConstance;

/**
 * 权限拦截器
 * 
 * @author JIANGYOUYAO
 * @email 935090232@qq.com
 * @date 2017年11月30日
 */
public class AuthorityInterceptor implements HandlerInterceptor {

	private UrlPathHelper urlPathHelper = new UrlPathHelper();
	private PathMatcher pathMatcher = new AntPathMatcher();
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object obj) throws Exception {

		// 开发人员和超级管理员具有所有权限，这段代码如果在生产环境建议删除，避免系统漏洞
		SysUsers user = WebUtil.getSessionAttribute(MatrixConstance.LOGIN_KEY);
		if (AppConstance.USER_TYPE_DEVELOPER.equals(user.getSuUserType())
				|| AppConstance.USER_TYPE_SUPER.equals(user.getSuUserType())) {
			return true;
		}
		
		
		// 用户已经登录校验权限
		List<String> mapping = WebUtil.getSessionAttribute(DefaultAuthorityManager.USER_URL_MAPPING);
		// 是否允许访问
		boolean isAccess = false;

		String lookupPath = urlPathHelper.getLookupPathForRequest(request);
		LogUtil.debug("request url =" + lookupPath);
		isAccess = mapping.contains(lookupPath);
		if (!isAccess) {

			LogUtil.debug("未匹配到用户权限，尝试通过正则表达式查找");

			List<String> matchingPatterns = new ArrayList<>();
			for (String registeredPattern : mapping) {
				if (pathMatcher.match(registeredPattern, lookupPath)) {
					matchingPatterns.add(registeredPattern);
				} else {
					if (!registeredPattern.endsWith("/") && pathMatcher.match(registeredPattern + "/", lookupPath)) {
						matchingPatterns.add(registeredPattern + "/");
					}
				}
			}

			// 获取到请求对应的正则表达式路径
			String bestMatch = null;
			Comparator<String> patternComparator = pathMatcher.getPatternComparator(lookupPath);
			if (!matchingPatterns.isEmpty()) {
				Collections.sort(matchingPatterns, patternComparator);
				LogUtil.debug("请求的匹配模式 [" + lookupPath + "] = " + matchingPatterns);
				bestMatch = matchingPatterns.get(0);
			}
			// 根据正则表达式，查询mapping中是否存在对应的路径
			if (bestMatch != null) {

				isAccess = mapping.contains(bestMatch);

				if (!isAccess) {
					if (bestMatch.endsWith("/")) {
						isAccess = mapping.contains(bestMatch.substring(0, bestMatch.length() - 1));
					}
					if (!isAccess) {
						LogUtil.debug("在用户权限列表中没有匹配到对应的正则表达式路径");
						throw new GlobleException(SystemErrorCode.PERMISSION_DENIED);
					}
				}
			} else {
				LogUtil.debug("在用户权限列表中没有匹配到对应的正则表达式路径");
				throw new GlobleException(SystemErrorCode.PERMISSION_DENIED);
			}
		}
		return isAccess;
	}

	@Override
	public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
			throws Exception {
	}
	@Override
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
			throws Exception {
	}
}
